'''
Created on 2014/03/21

@author: phuvieng
'''
# Aloha2.py, Python simulation example: a form of slotted ALOHA
# goal is to study response time (mean number of attempts needed to send
# a message), as a function of p

# usage: python Aloha2.py s p q

import random, sys

class node:
    s = int(sys.argv[1])  # number of nodes
    p = float(sys.argv[2])  # transmit probability
    q = float(sys.argv[3])  # msg creation probability
    totsent = 0  # number of msgs sent successfully by all nodes so far
    totwait = 0  # total wait time for those msgs
    activeset = []  # which nodes are active now (empty list for now)
    inactiveset = []  # which nodes are inactive now
    r = random.Random(98765)  # set seed
    def __init__(self):  # object constructor
        # start this node in inactive mode
        node.inactiveset.append(self)
        # the number of epochs this node's current msg has been waiting:
        self.wait = None  # currently undefined
    # class methods
    def checkgoactive():  # determine which nodes will go active
        for n in node.inactiveset:  # n is local to this function
            if node.r.uniform(0, 1) < node.q:
                node.inactiveset.remove(n)
                node.activeset.append(n)
                n.wait = 0
    checkgoactive = staticmethod(checkgoactive)  # make this a class method
    def trysent():
        numnodestried = 0  # number of nodes which have tried to send during the current epoch
        whotried = None  # which node tried to send (last)
        # determine which nodes try to send
        for n in node.activeset:
            n.wait += 1
            if node.r.uniform(0, 1) < node.p:
                whotried = n
                numnodestried += 1
        if numnodestried == 1:
            node.totsent += 1
            node.totwait += whotried.wait
            node.activeset.remove(whotried)
            node.inactiveset.append(whotried)
            
    trysent = staticmethod(trysent)
def main():
    for i in range(node.s): node()
    for epoch in range(1000):  # simulate 10000 (approx. "infinity") epochs
        node.checkgoactive()
        node.trysent()
    print 'mean time to get through =', node.totwait / float(node.totsent)
if __name__ == '__main__' : main()